package com.mall.cloud.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 核心过滤器
 * ServletDetectionFilter	pre	-3	检测当前请求是通过DispatcherServlet处理运行的还是ZuulServlet运行处理的。
 * Servlet30WrapperFilter	pre	-2	对原始的HttpServletRequest进行包装。
 * FormBodyWrapperFilter	pre	-1	将Content-Type为application/x-www-form-urlencoded或multipart/form-data的请求包装成FormBodyRequestWrapper对象。
 * DebugFilter	route	1	根据zuul.debug.request的配置来决定是否打印debug日志。
 * PreDecorationFilter	route	5	对当前请求进行预处理以便执行后续操作。
 * RibbonRoutingFilter	route	10	通过Ribbon和Hystrix来向服务实例发起请求，并将请求结果进行返回。
 * SimpleHostRoutingFilter	route	100	只对请求上下文中有routeHost参数的进行处理，直接使用HttpClient向routeHost对应的物理地址进行转发。
 * SendForwardFilter	route	500	只对请求上下文中有forward.to参数的进行处理，进行本地跳转。
 * SendErrorFilter	post	0	当其他过滤器内部发生异常时的会由它来进行处理，产生错误响应。
 * SendResponseFilter	post	1000	利用请求上下文的响应信息来组织请求成功的响应内容。
 */
@Component
public class PreLogFilter extends ZuulFilter {
    private Logger LOGGER = LoggerFactory.getLogger(this.getClass());

    /**
     * 过滤器类型，有pre、routing、post、error四种
     * pre：在请求被路由到目标服务前执行，比如权限校验、打印日志等功能；
     * routing：在请求被路由到目标服务时执行，这是使用Apache HttpClient或Netflix Ribbon构建和发送原始HTTP请求的地方；
     * post：在请求被路由到目标服务后执行，比如给目标服务的响应添加头信息，收集统计数据等功能；
     * error：请求在其他阶段发生错误时执行。
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 过滤器执行顺序，数值越小优先级越高
     * @return
     */
    @Override
    public int filterOrder() {
        return 1;
    }

    /**
     * 是否执行过滤，true会执行过滤
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 自定义的过滤器逻辑，当shouldFilter()返回true时会执行
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        String host = request.getRemoteUser();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        LOGGER.info("Remote host:{},method:{},uri:{}", host, method, uri);
        return null;
    }
}
